package com.example.demo.util;

import org.ofdrw.converter.utils.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Description: java类作用描述
 * @Author: zwx
 * @CreateDate: 2019/9/10 22:39
 */
public class DateTimeUtil {

    /**
     * 1 代表 -
     * 2 代表 汉字
     * 3 代表 /
     * 4 代表 :
     * _ 代表 空格
     */
    public static final String yyyyMMdd = "yyyyMMdd";
    public static final String yyyy1MM1dd = "yyyy-MM-dd";
    public static final String yyyy2MM2dd = "yyyy年MM月dd日";
    public static final String yyyy1MM1dd_HH4mm = "yyyy-MM-dd HH:mm";
    public static final String yyyy1MM1dd_HH4mm4ss = "yyyy-MM-dd HH:mm:ss";
    public static final String yyyy2MM2dd_HH2mm = "yyyy年 MM月 dd日 HH时 mm分";
    public static final Integer mOrW = 1;

    /**
     * 存放不同的日期模板格式的sdf的Map
     */
    private static Map<String, ThreadLocal<SimpleDateFormat>> sdfMap = new HashMap<>();

    private static SimpleDateFormat getSdf(final String pattern) {
        ThreadLocal<SimpleDateFormat> tl = sdfMap.get(pattern);
        // 此处的双重判断和同步是为了防止sdfMap这个单例被多次put重复的sdf
        if (tl == null) {
            tl = sdfMap.get(pattern);
            if (tl == null) {
                // 只有Map中还没有这个pattern的sdf才会生成新的sdf并放入map
//                System.out.println("put new sdf of pattern " + pattern + " to map");
                // 这里是关键,使用ThreadLocal<SimpleDateFormat>替代原来直接new SimpleDateFormat
                tl = ThreadLocal.withInitial(() -> {
                    System.out.println("thread: " + Thread.currentThread() + " init pattern: " + pattern);
                    return new SimpleDateFormat(pattern);
                });
            }
            sdfMap.put(pattern, tl);
        }
        return tl.get();
    }

    public static Date longToDate(Long longTime) {
        if (longTime == null || longTime == 0)
            return null;
        return new Date(longTime);
    }

    public static String longToStr(Long longTime, String pattern) {
        if (longTime == null) {
            return "";
        }
        if (StringUtils.isBlank(pattern)) {
            pattern = yyyy1MM1dd_HH4mm;
        }
        SimpleDateFormat sdf = getSdf(pattern);
        return sdf.format(new Date(longTime));
    }

    public static String longToStr(Long longTime) {
        return longToStr(longTime, yyyy1MM1dd_HH4mm4ss);
    }

    public static String dateToStr(Date date) {
        return longToStr(date.getTime());
    }

    public static String dateToStr(Date date, String pattern) {
        return longToStr(date.getTime(), pattern);
    }

    public static Long dateToLong(Date date) {
        if (date == null) return null;
        return date.getTime();
    }

    public static Date strToDate(String str, String pattern) {
        if (StringUtils.isBlank(str)) return null;
        if (StringUtils.isBlank(pattern)) {
            pattern = yyyy1MM1dd_HH4mm;
        }
        SimpleDateFormat sdf = getSdf(pattern);
        try {
            return sdf.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static Date strToDate(String str) {
        return strToDate(str, yyyy1MM1dd_HH4mm);
    }

    /*
     *   获取下下个月初时间戳
     */
    public static Long nextMonthLastToLong(Calendar calendar) {
        calendar.add(Calendar.MONTH, 2);
        calendar.set(Calendar.DAY_OF_MONTH, 2);
        calendar.set(Calendar.HOUR_OF_DAY, 00);
        calendar.set(Calendar.MINUTE, 00);
        calendar.set(Calendar.SECOND, 00);
        return DateTimeUtil.dateToLong(calendar.getTime());
    }

    /*
     *   获取指定月份-月初时间
     *   return Date
     */
    public static Date appointYearMonthFirst(int year, int month) {
        Calendar cal = Calendar.getInstance();
        //设置年份
        cal.set(Calendar.YEAR, year);
        //设置月份
        cal.set(Calendar.MONTH, month - 1);
        //获取某月最小天数
        int firstDay = cal.getActualMinimum(Calendar.DAY_OF_MONTH);
        //设置日历中月份的最大天数
        cal.set(Calendar.DAY_OF_MONTH, firstDay);
        cal.set(Calendar.HOUR_OF_DAY, 00);
        cal.set(Calendar.MINUTE, 00);
        cal.set(Calendar.SECOND, 00);
        return cal.getTime();
    }

    /*
     *   获取指定月份-月末时间
     *   return Date
     */
    public static Date appointYearMonthLast(int year, int month) {
        Calendar cal = Calendar.getInstance();
        //设置年份
        cal.set(Calendar.YEAR, year);
        //设置月份
        cal.set(Calendar.MONTH, month - 1);
        //获取某月最大天数
        int lastDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
        //设置日历中月份的最大天数
        cal.set(Calendar.DAY_OF_MONTH, lastDay);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return cal.getTime();
    }

    /*
     *   判断当前时间是否为周一/每月一号
     *   return Boolean
     */
    public static Boolean judgeTime() {
        Calendar cal = Calendar.getInstance();
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        int m = cal.get(Calendar.DAY_OF_MONTH);
        System.out.println(m + "----" + w);
        if (Objects.equals(w, mOrW) || Objects.equals(m, mOrW)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 获取前一天日期字符串
     *
     * @return
     */
    public static String getBeforeToday() {
        SimpleDateFormat sdf = getSdf(yyyyMMdd);
        Date date = new Date();
        Calendar now = Calendar.getInstance();
        now.setTime(date);
        now.add(Calendar.DAY_OF_MONTH, -1);
        return sdf.format(now.getTime());
    }

    public static Date appointYearFirst(Integer year) {
        Calendar cal = Calendar.getInstance();
        cal.clear();
        //设置年份
        cal.set(Calendar.YEAR, year);
        return cal.getTime();
    }

    public static Date appointYearLast(Integer year) {
        Calendar cal = Calendar.getInstance();
        cal.clear();
        //设置年份
        cal.set(Calendar.YEAR, year);
        cal.roll(Calendar.DAY_OF_YEAR, -1);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return cal.getTime();
    }

    public static String getToday() {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        String monthStr = month < 10? "0" + month: String.valueOf(month);
        String dayStr = day < 10? "0" + day: String.valueOf(day);
        return year + monthStr + dayStr;
    }
    /**
     * 日期计算
     *
     * @param sourceDate
     * @param addYear
     * @param addMonth
     * @param addDate
     * @return 输入Date
     * @throws Exception
     */
    public static Date calculate(Date sourceDate, int addYear, int addMonth, int addDate) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(sourceDate);
        cal.add(Calendar.YEAR, addYear);
        cal.add(Calendar.MONTH, addMonth);
        cal.add(Calendar.DATE, addDate);
        return cal.getTime();
    }
}
